package com.igoal.service;

import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import com.igoal.dto.GoalDTO;
import com.igoal.dto.UserDTO;
import com.igoal.dto.UserGoalDTO;
import com.igoal.dto.UserGoalPhaseDTO;
import com.igoal.dto.UserGoalTaskDTO;
import com.igoal.entity.UserGoal;
import com.igoal.entity.UserGoalPk;
import com.igoal.web.Constants;

public interface UserGoalManager extends GenericManager<UserGoal, UserGoalPk> {
	/**
	 * Get list of doing goal of user
	 * 
	 * @param userId
	 *            user pk
	 * @return List of {@link UserGoal}
	 */
	@Transactional(readOnly = true)
	List<UserGoalDTO> getDoingGoal(Long userId);

	/**
	 * Get list of completed goal of user
	 * 
	 * @param userId
	 *            user pk
	 * @return List of {@link UserGoal}
	 */
	@Transactional(readOnly = true)
	List<UserGoalDTO> getCompletedGoal(Long userId);

	/**
	 * User create new goal
	 * 
	 * @param goal
	 *            the model of goal {@link GoalDTO}
	 * @param user
	 *            the user that add this goal {@link UserDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	UserGoalDTO createNewGoal(GoalDTO goal, UserDTO user);
	
	/**
	 * Each user can create a fixed goals per day {@link Constants}
	 * @param user who does that
	 * @return True if allowed otherwise False
	 */
	@Transactional(readOnly = true)
	boolean allowCreateNewGoal(UserDTO user);
	
	/**
	 * Check if user attempt create a duplicate goal
	 * @param username who does that
	 * @param goalTitle title of goal will be checked
	 * @return True if it exists otherwise False
	 */
	@Transactional(readOnly = true)
	boolean isThisGoalInUserGoalList(String username, String goalTitle);
	
	/**
	 * Find a user goal by user identifier and goal identifier
	 * @param userId user identifier
	 * @param goalId goal identifier
	 * @return found {@link UserGoalDTO} or null if cannot find
	 */
	@Transactional(readOnly = true)	
	UserGoalDTO getUserGoalByPrimaryKey(Long userId, Long goalId);
	
	/**
	 * Remove a goal from user
	 * 
	 * @param username
	 * @param goalId
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int deleteUserGoal(String username, Long goalId);
	
	/**
	 * Mark goal as done 
	 * 
	 * @param username
	 * @param goalId
	 * @return
	 */
	@Transactional(readOnly = false)
	int achieveGoal(String username, Long goalId);
	
	/**
	 * Do this goal
	 * 
	 * @param username
	 * @param goalId
	 * @return
	 */
	@Transactional(readOnly = false)
	int doGoal(String username, Long goalId);
	
	/**
	 * Update user goal finished percentage
	 * @param username who does that
	 * @param goalId goal identifier
	 * @param percent percentage
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int updateUserGoalPercent(String username, Long goalId, Integer percent);
	
	/**
	 * Get goals of user by page with some criteria inside <code>MAP</code>
	 * @param criteria criteria map
	 * @param orderProperty order property name
	 * @param lastOrderPropertyValue the value that order property value must greater or less than
	 * @param before page before previous page or after
	 * @return list {@link UserGoalDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalDTO> getUserGoalsByPaging(Map<String, Object> criteria, String orderProperty, Object lastOrderPropertyValue, boolean before);
	
	/**
	 * Get todo list of an user goal
	 * @param username goal owner name
	 * @param goalId goal id
	 * @return list {@link UserGoalTaskDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalTaskDTO> getTodoList(String username, Long goalId);
	
	/**
	 * Add a task
	 * @param username owner of task
	 * @param task task detail
	 * @return {@link SaveResult}
	 */
//	@Transactional(readOnly = false)
//	int addTaskToUserGoal(String username, UserGoalTaskDTO task);
	
	/**
	 * Add list of task
	 * @param username owner of tasks
	 * @param tasks list of task
	 * @return {@link SaveResult}
	 */
//	@Transactional(readOnly = false)
//	int addTasksToUserGoal(String username, List<UserGoalTaskDTO> tasks);
	
	/**
	 * Update task detail
	 * @param username owner of task
	 * @param task task detail
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int updateTask(String username, UserGoalTaskDTO task);
	
	/**
	 * Finish task
	 * @param username owner of task
	 * @param taskId task identifier
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int finishTask(String username, Long taskId);
	
	@Transactional(readOnly = false)
	int uncompleteTask(String username, Long taskId);
	
	/**
	 * Delete a task
	 * @param username owner of task
	 * @param taskId task identifier
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int deleteTask(String username, Long taskId);
	
	/**
	 * Get uncomplete tasks of all goals of user
	 * @param username owner of tasks
	 * @return list {@link UserGoalTaskDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalTaskDTO> getUnCompleteTasks(String username);
	
	/**
	 * Get uncomplete tasks of a goal of user
	 * @param username owner of tasks
	 * @param goalId goal identifier
	 * @return list {@link UserGoalTaskDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalTaskDTO> getUnCompleteTasks(String username, Long goalId);
	
	/**
	 * Get all of tasks of user that their deadlines are coming to <i>days</i>
	 * @param username
	 * @return
	 */
	@Transactional(readOnly = true)
	List<UserGoalTaskDTO> notifyNearDeadLineTasks(String username);
	
	/**
	 * Add SMART Goal
	 * @param username owner of this smart goal
	 * @param userGoal some need information like goal title
	 * @param phases list of phase
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int addOrUpdateSMARTGoal(String username, UserGoalDTO userGoal, List<UserGoalPhaseDTO> phases);
	
	@Transactional(readOnly = true)
	List<UserGoalPhaseDTO> getPhaseList(String username, Long goalId);
	
	@Transactional(readOnly = false)
	int updatePhases(String username, List<UserGoalPhaseDTO> phases);
}
